package app

import (
	"fmt"
	"net/http"
	"html/template"
	"log"
	"encoding/json"

	"github.com/tidwall/gjson"
	"strings"
	"time"
)

type SaltHostListJson struct {
	Return []struct {
		Data struct {
			Return struct {
				Minions []string `json:"minions"`
			} `json:"return"`
		} `json:"data"`
	} `json:"return"`
}

//saltstack 主机列表
func (G *Global) Hosts(w http.ResponseWriter, r *http.Request) {
	if NodesAll, Err := G.SelectAll("SELECT * FROM hosts"); Err == nil {
		out := map[string]interface{}{"Global": G, "NodesAll": NodesAll}
		t, template_err := template.ParseFiles("templates/salt/hosts.html", "templates/common/head.html", "templates/common/foot.html")
		if template_err != nil {
			log.Println(template_err.Error())
			fmt.Fprintf(w, template_err.Error())
		} else {
			t.Execute(w, out)
		}
	} else {
		fmt.Println(Err.Error())
	}
}

//获取saltstack minion列表
func (G *Global) SaltHostList() ([]string, error) {
	post_data := fmt.Sprintf(`{"fun": "%s", "client": "%s"}`, "key.list_all", "wheel")
	DATA, CMD_SALT_ERR := G.Salt.CMD_SALT(post_data)
	if CMD_SALT_ERR != nil {
		return []string{}, CMD_SALT_ERR
	} else {
		var JsonRes SaltHostListJson
		json.Unmarshal([]byte(string(DATA)), &JsonRes)
		return JsonRes.Return[0].Data.Return.Minions, nil
	}

}

//获取saltstack 单个minion详细信息
func (G *Global) SaltHostInfo(id string) (string, error) {
	post_data := fmt.Sprintf(`{"fun": "%s", "client": "%s", "tgt": "%s"}`, "grains.items", "local", id)
	DATA, CMD_SALT_ERR := G.Salt.CMD_SALT(post_data)
	if CMD_SALT_ERR != nil {
		return "", CMD_SALT_ERR
	} else {
		return DATA, nil
	}
}

//更新主机信息
func (G *Global) Update_Hosts(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		SaltHostList, Err := G.SaltHostList() // 获取主机列表
		if Err == nil {
			//清理不存在主机
			if HostInfo, Err := G.SelectAll("SELECT hosts_id,id FROM hosts"); Err == nil {
				for _, j := range *HostInfo {
					if ! G.CheckStrings(SaltHostList, j["id"]) {
						if _, Err := G.Delete("DELETE FROM `hosts` where hosts_id=?", j["hosts_id"]); Err != nil {
							log.Println(Err.Error())
							fmt.Fprint(w, Get_Json("系统错误!"))
							return
						}
					}
				}
			} else {
				log.Println(Err.Error())
				fmt.Fprint(w, Get_Json("系统错误!"))
			}
			for _, i := range SaltHostList { //循环salt主机列表
				SaltHostInfo, Err := G.SaltHostInfo(i)  //获取单个主机详细信息
				if Err == nil {
					if HostInfo, Err := G.SelectOne("SELECT * FROM hosts where id = ?", i); Err == nil {  //查询当前数据库中,该主机信息
						Value := fmt.Sprintf(strings.Replace(i, ".", `\.`, -1))
						if gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s`, Value)).Array()[0].String() == "false" {  //如果主机信息返回的是 false
							G.Update("UPDATE  hosts SET  status=? WHERE id = ?", "离线", i)
						} else {
							if len(HostInfo) == 0 { // 表示数据库中不存在该主机信息 ； 就向数据库插入该数据
								if _, Err := G.Insert("INSERT INTO hosts (server_id, id, host, os, osrelease, kernelrelease, ipaddr, num_cpus, mem_total,virtual, productname,selinux,add_time,status) VALUES (?, ?,?, ?,?, ?,?, ?,?, ?,?, ?,?,?)",
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.server_id`, Value)).Array()[0].String(),                   //1
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.id`, Value)).Array()[0].String(),                          //2
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.host`, Value)).Array()[0].String(),                        //3
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.os`, Value)).Array()[0].String(),                          //4
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.osrelease`, Value)).Array()[0].String(),                   //5
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.kernelrelease`, Value)).Array()[0].String(),               //6
									//gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.fqdn_ip4`, Value)).Array()[0].Array()[0].String(),         //7
									"",
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.num_cpus`, Value)).Array()[0].String(),                    //8
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.mem_total`, Value)).Array()[0].String(),                   //9
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.virtual`, Value)).Array()[0].String(),                     //10
									//gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.productname`, Value)).Array()[0].String(),                 //11
									"",
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.selinux.enforced`, Value)).Array()[0].Array()[0].String(), //12
									time.Now().Format("2006-01-02 15:04:05"),
									"正常",
									"正常",); Err != nil {
									log.Println(Err)
									fmt.Fprint(w, Get_Json("系统错误!"))
									return
								}
							} else { // 存在进行更新操作
								if _, Err := G.Update("UPDATE  hosts SET  status=?,host=?, os=?, osrelease=?, kernelrelease=?, ipaddr=?, num_cpus=?, mem_total=?,virtual=?, productname=?,selinux=?,up_time=? WHERE server_id=? AND id =?",
									"正常",
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.host`, Value)).Array()[0].String(),                        //3
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.os`, Value)).Array()[0].String(),                          //4
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.osrelease`, Value)).Array()[0].String(),                   //5
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.kernelrelease`, Value)).Array()[0].String(),               //6
									//gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.fqdn_ip4`, Value)).Array()[0].Array()[0].String(),         //7
									"",
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.num_cpus`, Value)).Array()[0].String(),                    //8
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.mem_total`, Value)).Array()[0].String(),                   //9
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.virtual`, Value)).Array()[0].String(),                     //10
									//gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.productname`, Value)).Array()[0].String(),                 //11
									"",
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.selinux.enforced`, Value)).Array()[0].Array()[0].String(), //12
									time.Now().Format("2006-01-02 15:04:05"),
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.server_id`, Value)).Array()[0].String(), //1
									gjson.Get(SaltHostInfo, fmt.Sprintf(`return.#.%s.id`, Value)).Array()[0].String(),        //2
								); Err != nil {
									log.Println(Err.Error())
									fmt.Fprint(w, Get_Json("系统错误!"))
									return
								}
							}
						}
					} else {
						log.Println(Err.Error())
						fmt.Fprint(w, Get_Json("系统错误!"))
					}
				} else {
					log.Println(Err.Error())
					fmt.Fprint(w, Get_Json("系统错误!"))
				}
			}
			fmt.Fprint(w, Get_Json("Success"))
		} else {
			log.Println(Err.Error())
			fmt.Fprint(w, Get_Json("系统错误!"))
		}
	}
}

//模板列表
func (G *Global) SaltTemplate(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		if TemplateAll, Err := G.SelectAll("SELECT * FROM salt_template"); Err == nil {
			out := map[string]interface{}{"Global": G, "TemplateAll": TemplateAll}
			t, template_err := template.ParseFiles("templates/salt/template.html", "templates/common/head.html", "templates/common/foot.html")
			if template_err != nil {
				log.Println(template_err.Error())
				fmt.Fprintf(w, template_err.Error())
			} else {
				t.Execute(w, out)
			}
		} else {
			fmt.Println(Err.Error())
		}
	} else if r.Method == "POST" {
		if _, Err := G.Update("UPDATE salt_template SET template_txt= ? , up_time = ? WHERE id = ?", r.PostFormValue("txt"), time.Now().Format("2006-01-02 15:04:05"), r.PostFormValue("id")); Err == nil {
			fmt.Fprint(w, Get_Json("编辑成功!"))
		} else {
			fmt.Fprint(w, Get_Json("编辑失败!"))
			log.Println(Err.Error())
		}
	}

}

// 更新saltstack-template
func (G *Global) SaltTemplateEdit(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		if _, Err := G.Update("UPDATE salt_template SET template_txt= ? , up_time = ? WHERE id = ?", r.PostFormValue("txt"), time.Now().Format("2006-01-02 15:04:05"), r.PostFormValue("id")); Err == nil {
			fmt.Fprint(w, Get_Json("编辑成功!"))
		} else {
			fmt.Fprint(w, Get_Json("编辑失败!"))
			log.Println(Err.Error())
		}
	}
}

// 添加saltstack-template
func (G *Global) SaltTemplateAdd(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		if TemplateInfo, Err := G.SelectOne("SELECT template_name FROM salt_template WHERE template_name =?", r.PostFormValue("salt_template_name")); Err == nil {
			if TemplateInfo["template_name"] == r.PostFormValue("salt_template_name") {
				fmt.Fprint(w, Get_Json("模板名称重复!"))
				return
			} else {
				if _, Err := G.Insert("INSERT INTO `salt_template` (`template_txt`, `template_name`, `add_time`) VALUES (?,?,?)", r.PostFormValue("salt_template_txt"), r.PostFormValue("salt_template_name"), time.Now().Format("2006-01-02 15:04:05")); Err == nil {
					fmt.Fprint(w, Get_Json("Success"))
				} else {
					fmt.Fprint(w, Get_Json("系统错误!"))
					log.Println(Err.Error())
				}
			}
		}
	}
}

// 删除saltstack-template
func (G *Global) SaltTemplateDel(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		if _, Err := G.Delete("DELETE FROM salt_template WHERE id=?", r.PostFormValue("id")); Err == nil {
			fmt.Fprint(w, Get_Json("Success"))
		} else {
			log.Println(Err.Error())
			fmt.Fprint(w, Get_Json("删除失败!"))
		}
	}
}

func (G *Global) NODECMD(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		hostname := r.PostFormValue("hostname")
		cmd := r.PostFormValue("cmd")
		//arg := r.PostFormValue("arg")
		fmt.Println(hostname, cmd)
		post_cmd := fmt.Sprintf(`{"fun": "%s", "client": "%s", "tgt": "%s" ,"arg": "%s"}`, "cmd.run", "local", hostname, cmd)
		if cmd == "" || cmd == "*rm*" || cmd == "init" {
			fmt.Fprintf(w, "命令非法")
		} else {
			REDATA, ERR := G.Salt.CMD_SALT(post_cmd) //解析域名
			if ERR == nil {
				fmt.Fprintf(w, REDATA)
				fmt.Print("SALT执行命令", post_cmd)
			} else {
				fmt.Print("命令执行错误")
			}
		}
	}
}
